package gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import modelcontroller.Conversation;
import modelcontroller.User;

/**
 *
 * @author Mariam
 */
public final class ChatWindow extends JFrame implements ActionListener, MouseListener {

    private ChatGUI parent;
    private JMenuBar menu;
    private JSplitPane splitPane;
    private ArrayList<ConversationArea> conversations;
    private JList listUsers;
    private JTextArea msgToSend;
    private JButton bSend;
    private JButton bSendFile;
    private JTabbedPane tabbedPane;
    private JMenuItem disconnect;
    private JMenuItem exit;
    private JMenuItem help;
    private JMenuItem infos;

    /**
     * Constructs the main chat window where is display the list of the
     * connected users, the conversations with other peers, the tools to send
     * messages and files
     *
     * @param parent the GUI which has created the window
     */
    public ChatWindow(ChatGUI parent) {
        super();
        this.parent = parent;
        initComponents();
    }

    private void initComponents() {
        // ********* INIT MENU ********* //
        menu = new JMenuBar();
        JMenu filemenu = new JMenu("File");
        JMenu helpmenu = new JMenu("About");
        disconnect = new JMenuItem("Disconnect");
        filemenu.add(disconnect);
        exit = new JMenuItem("Exit");
        filemenu.add(exit);
        help = new JMenuItem("Help");
        helpmenu.add(help);
        infos = new JMenuItem("Infos");
        infos.setText("Local User : " + parent.model.getLocalUser().toString());
        helpmenu.add(infos);
        menu.add(filemenu);
        menu.add(helpmenu);
        disconnect.addActionListener(this);
        exit.addActionListener(this);
        help.addActionListener(this);

        // ********* INIT LIST OF CONNECTED USERS ********* //
        listUsers = new JList(parent.model.getConnectedUsers());
        JScrollPane scrollPanelist = new JScrollPane(listUsers, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        listUsers.setPrototypeCellValue("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");

        // ********* INIT PANEL OF CONVERSATIONS ********* //
        conversations = new ArrayList<ConversationArea>();
        conversations.add(ConversationArea.welcomeConversationArea(parent.model.getLocalUser().getUsername()));
        tabbedPane = new JTabbedPane();
        JScrollPane scroll = new JScrollPane(conversations.get(0));
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        tabbedPane.add(scroll);
        tabbedPane.setTitleAt(0, "Welcome");
        tabbedPane.addMouseListener(this);

        // ********* INIT SEND PANEL ********* //
        msgToSend = new JTextArea(4, 25);
        bSend = new JButton("Send");
        bSendFile = new JButton("Send File");
        bSendFile.addActionListener(this);
        bSend.addActionListener(this);
        splitPane = new JSplitPane(1, new JSplitPane(0, bSend, bSendFile), msgToSend);

        // ********* INIT LAYOUT ********* //
        this.setLayout(new BorderLayout());
        this.add(BorderLayout.NORTH, menu);
        this.add(BorderLayout.EAST, tabbedPane);
        this.add(BorderLayout.WEST, scrollPanelist);
        this.add(BorderLayout.SOUTH, splitPane);

        // ********* FORMAT WINDOW ********* //
        this.pack();
        this.setTitle("Chat System");
        this.setVisible(true);


        listUsers.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent arg0) {
                if (listUsers.getSelectedValue() != null && listUsers.getModel().getSize() != 0 && !arg0.getValueIsAdjusting()
                        && (parent.model.getHashmapConv().get((User) listUsers.getSelectedValue())) == null) {
                    selectUser();
                }
            }
        });

        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent windowEvent) {
                parent.disconnect();
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == bSend && listUsers.getSelectedValue() != null) {
            sendMsg();
        } else if (e.getSource() == bSendFile && listUsers.getSelectedValue() != null) {
            sendFile();
        } else if (e.getSource() == disconnect) {
            parent.disconnect();
            this.dispose();
        } else if (e.getSource() == exit) {
            parent.disconnect();
            System.exit(0);
        } else if (e.getSource() == help) {
            JOptionPane.showMessageDialog(rootPane, "[Help]\n"
                    + "- To disconnect: File > Disconnect or click on cross icon\n"
                    + "- To close a conversation tab: click right on it\n"
                    + "- For any help or further info: please contact Mariam Kadoura");
        }
    }

    /**
     * Refreshes the list of the connected users
     */
    protected void updateUsersList() {
        if (parent.model.getLocalUserIsConnected()) {
            listUsers.setCellRenderer(new ListCellRenderer());
            this.pack();
        }
    }

    /**
     * Signal from the user that he wants to start a conversation with the
     * selected peer
     */
    protected void selectUser() {
        int choice = JOptionPane.showConfirmDialog(rootPane, "Do you want to start a chat with " + listUsers.getSelectedValue().toString() + " ?");
        if (choice == 0) {
            parent.selectUser((User) listUsers.getSelectedValue());
        } else {
            listUsers.clearSelection();
        }
    }

    /**
     * Opens a new tab where the conversation will be displayed
     * 
     * @param conversation the new conversation to display
     */
    protected void openConversation(Conversation conversation) {
        ConversationArea ca = new ConversationArea(conversation);
        conversations.add(ca);
        JScrollPane scroll = new JScrollPane(ca,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        Component component = tabbedPane.add(scroll);
        tabbedPane.setSelectedComponent(component);
        tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), conversation.getRemoteUser().toString());
        listUsers.setSelectedValue(conversation.getRemoteUser(), true);
        this.pack();
    }

    /**
     * Deletes the selected conversation tab
     */
    protected void closeConversation() {
        // we cannot close the welcome tab
        if (!tabbedPane.getTitleAt(tabbedPane.getSelectedIndex()).equals("Welcome")) {
            ConversationArea area = conversations.get(tabbedPane.getSelectedIndex());
            tabbedPane.remove(tabbedPane.getSelectedComponent());
            parent.model.removeConversation(area.getConversation());
            conversations.remove(area);
        }
    }

    /**
     * Refreshes the conversations currently displayed
     */
    protected void updateConversationsList() {
        if (parent.model.getLocalUserIsConnected()) {
            for (int i = 1; i < tabbedPane.getTabCount(); i++) {
                ConversationArea area = conversations.get(i);
                area.setText(area.getConversation().getHistory());
            }
        }
    }

    /**
     * Signal from the user that he wants to send a message to a peer user
     */
    protected void sendMsg() {
        User user = conversations.get(tabbedPane.getSelectedIndex()).getConversation().getRemoteUser();
        parent.sendMessage(user.getUsername(), msgToSend.getText());
        msgToSend.setText(""); // clear text zone
    }

    /**
     * Signal from the user that he wants to send a file to a peer user
     */
    protected void sendFile() {
        User user = conversations.get(tabbedPane.getSelectedIndex()).getConversation().getRemoteUser();
        JFileChooser filechooser = new JFileChooser();
        int val = filechooser.showOpenDialog(rootPane);
        if (val == JFileChooser.APPROVE_OPTION) {
            parent.sendFile(user.getUsername(), filechooser.getSelectedFile().getName(),
                    filechooser.getSelectedFile().getAbsolutePath(), filechooser.getSelectedFile().length());
        }
    }

    /**
     * Displays the proposition from a remote user to send a file
     *
     * @param username the login of the sender of the request
     * @param filename the name of the file that is proposed to the local user
     * @return the user's reply: true if he wants to receive the file, false if
     * he refuses
     */
    protected boolean displayFileRequest(String username, String filename) {
        int choice = JOptionPane.showConfirmDialog(rootPane,
                "Do you want to accept this file: '" + filename + "' from " + username,
                "File", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
        return choice == 0;
    }

    /**
     * Displays the file chooser window to ask the user where he wants to
     * locate the file that he is going to receive
     *
     * @return the path (location) where the user wants to download the file
     */
    protected String displayFilepathRequest() {
        JFileChooser filechooser = new JFileChooser();
        filechooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        filechooser.setDialogTitle("Choose a directory destination");
        filechooser.showOpenDialog(rootPane);
        return filechooser.getSelectedFile().getAbsolutePath();
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON3) { // right click
            closeConversation();
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}
